package com.crm.controller.common;

import com.crm.common.result.AjaxResult;
import com.crm.common.result.ResultVO;
import com.crm.common.utils.AliOssUtil;
import com.crm.common.utils.MinioUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;

/**
 * 文件上传控制器
 */
@Slf4j
@RestController
//@RequestMapping("/common")
@Tag(name = "文件管理", description = "文件上传、下载、删除等操作")
public class FileController {


    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private AliOssUtil aliOssUtil;

    /**
     * 上传单个文件
     */
    @PostMapping("/upload")
    @Operation(summary = "上传单个文件", description = "上传单个文件到MinIO")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return AjaxResult.error("文件不能为空");
            }
            //文件重命名uuid
            //文件原始名称
            String originalFileName = file.getOriginalFilename();
            //文件后缀
            String extension = originalFileName.substring(originalFileName.lastIndexOf("."));
            //文件重命名
            String objectName = UUID.randomUUID().toString() + extension;
            String fileUrl = aliOssUtil.upload(file.getBytes(), objectName);
            ResultVO<String> result = ResultVO.success(fileUrl);
            result.setMsg("文件上传成功");
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", fileUrl);
            ajax.put("fileName","/"+fileUrl);
            //ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return AjaxResult.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 上传文件到指定存储桶
     */
    @PostMapping("/upload/{bucketName}")
    @Operation(summary = "上传文件到指定存储桶", description = "上传文件到指定的MinIO存储桶")
    public ResultVO<String> uploadFileToBucket(@PathVariable String bucketName,
                                               @RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return ResultVO.error("文件不能为空");
            }

            String fileUrl = minioUtil.uploadFile(bucketName, file);
            ResultVO<String> result = ResultVO.success(fileUrl);
            result.setMsg("文件上传成功");
            return result;
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return ResultVO.error("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 批量上传文件
     */
    @PostMapping("/upload/batch")
    @Operation(summary = "批量上传文件", description = "批量上传多个文件到MinIO")
    public ResultVO<String[]> uploadFiles(@RequestParam("files") MultipartFile[] files) {
        try {
            if (files == null || files.length == 0) {
                return ResultVO.error("文件不能为空");
            }

            String[] fileUrls = new String[files.length];
            for (int i = 0; i < files.length; i++) {
                if (!files[i].isEmpty()) {
                    fileUrls[i] = minioUtil.uploadFile(files[i]);
                }
            }

            ResultVO<String[]> result = ResultVO.success(fileUrls);
            result.setMsg("文件批量上传成功");
            return result;
        } catch (Exception e) {
            log.error("文件批量上传失败", e);
            return ResultVO.error("文件批量上传失败: " + e.getMessage());
        }
    }

    /**
     * 下载文件
     */
    @GetMapping("/download")
    @Operation(summary = "下载文件", description = "从MinIO下载文件")
    public ResponseEntity<InputStreamResource> downloadFile(@RequestParam String fileName) {
        try {
            InputStream inputStream = minioUtil.downloadFile(fileName);
            InputStreamResource resource = new InputStreamResource(inputStream);

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
            headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
            headers.add(HttpHeaders.PRAGMA, "no-cache");
            headers.add(HttpHeaders.EXPIRES, "0");

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 从指定存储桶下载文件
     */
    @GetMapping("/download/{bucketName}")
    @Operation(summary = "从指定存储桶下载文件", description = "从指定的MinIO存储桶下载文件")
    public ResponseEntity<InputStreamResource> downloadFileFromBucket(@PathVariable String bucketName,
                                                                      @RequestParam String fileName) {
        try {
            InputStream inputStream = minioUtil.downloadFile(bucketName, fileName);
            InputStreamResource resource = new InputStreamResource(inputStream);

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
            headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
            headers.add(HttpHeaders.PRAGMA, "no-cache");
            headers.add(HttpHeaders.EXPIRES, "0");

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/delete")
    @Operation(summary = "删除文件", description = "从MinIO删除文件")
    public ResultVO<String> deleteFile(@RequestParam String fileName) {
        try {
            minioUtil.deleteFile(fileName);
            ResultVO<String> result = ResultVO.success("文件删除成功");
            result.setMsg("文件删除成功");
            return result;
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return ResultVO.error("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 删除指定存储桶中的文件
     */
    @DeleteMapping("/delete/{bucketName}")
    @Operation(summary = "删除指定存储桶中的文件", description = "从指定的MinIO存储桶删除文件")
    public ResultVO<String> deleteFileFromBucket(@PathVariable String bucketName,
                                                 @RequestParam String fileName) {
        try {
            minioUtil.deleteFile(bucketName, fileName);
            ResultVO<String> result = ResultVO.success("文件删除成功");
            result.setMsg("文件删除成功");
            return result;
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return ResultVO.error("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 检查文件是否存在
     */
    @GetMapping("/exists")
    @Operation(summary = "检查文件是否存在", description = "检查MinIO中文件是否存在")
    public ResultVO<Boolean> fileExists(@RequestParam String fileName) {
        try {
            boolean exists = minioUtil.fileExists(fileName);
            ResultVO<Boolean> result = ResultVO.success(exists);
            result.setMsg("查询成功");
            return result;
        } catch (Exception e) {
            log.error("文件存在性检查失败", e);
            return ResultVO.error("文件存在性检查失败: " + e.getMessage());
        }
    }

    /**
     * 检查指定存储桶中的文件是否存在
     */
    @GetMapping("/exists/{bucketName}")
    @Operation(summary = "检查指定存储桶中的文件是否存在", description = "检查指定MinIO存储桶中文件是否存在")
    public ResultVO<Boolean> fileExistsInBucket(@PathVariable String bucketName,
                                                @RequestParam String fileName) {
        try {
            boolean exists = minioUtil.fileExists(bucketName, fileName);
            ResultVO<Boolean> result = ResultVO.success(exists);
            result.setMsg("查询成功");
            return result;
        } catch (Exception e) {
            log.error("文件存在性检查失败", e);
            return ResultVO.error("文件存在性检查失败: " + e.getMessage());
        }
    }
}
